package com.fanrui.code.chess;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

import com.fanrui.code.chess.mahjong.BaoHuRules;
import com.fanrui.code.chess.mahjong.ClubMahjongTable;
import com.fanrui.code.chess.mahjong.GanZhouMahjongRules;
import com.fanrui.code.chess.mahjong.MahjongRules;
import com.fanrui.code.chess.mahjong.MahjongRules.CurrencyType;
import com.fanrui.code.chess.mahjong.MatchMahjongTable;
import com.fanrui.code.chess.mahjong.PrivateMahjongTable;
import com.fanrui.proto.cmd.MahjongBaseRoomConfig;
import com.fanrui.proto.cmd.MahjongGameType;
import com.fanrui.proto.cmd.MatchGameLevel;

public class ChessTableManager {
	
	private ChessTableManager() {}
	
	private static class ChessTableManagerSingleton {
		private static ChessTableManager instance = new ChessTableManager();
	}

	public static ChessTableManager getInstance() {
		return ChessTableManagerSingleton.instance;
	}
	
	/**
	 * 私人场占用了100000 - 999999的id，匹配场ID 1000000起
	 */
	private AtomicInteger idCreate = new AtomicInteger(1000000);
	
	/**
	 * 所有匹配场牌桌集合
	 */
	private ConcurrentMap<Integer, ITable> matchTables = new ConcurrentHashMap<Integer, ITable>();
	
	/**
	 * 所有私有场牌桌集合
	 */
	private ConcurrentMap<Integer, ITable> privateTables = new ConcurrentHashMap<Integer, ITable>();
	
	/**
	 * 私人牌桌的ID
	 */
	private static List<Integer> privateTableIds = new ArrayList<Integer>();

	/**
	 * 创建麻将匹配场
	 * 
	 * @return ITable
	 */
	public ITable create(MahjongBaseRoomConfig config, MahjongGameType gameType, MatchGameLevel gameLevel) {
		MahjongRules gameRules = createMahjongGameRules(config);
		gameRules.setCurrencyType(CurrencyType.Gold);
		MatchMahjongTable table = new MatchMahjongTable(idCreate.incrementAndGet(), gameRules, gameType, gameLevel);
		addMatchTable(table);
		return table;
	}
	
	/**
	 * 创建私人场
	 */
	public ITable create(MahjongBaseRoomConfig config, long roomer) {
		synchronized (privateTables) {
			MahjongRules gameRules = createMahjongGameRules(config);
			ITable table = new PrivateMahjongTable(getRandomRoomId(), gameRules, roomer);
			addPrivateTable(table);
			return table;
		}
	}
	
	/**
	 * 创建俱乐部房间
	 */
	public ITable create(MahjongBaseRoomConfig config, long roomer, long clubId) {
		synchronized (privateTables) {
			MahjongRules gameRules = createMahjongGameRules(config);
			gameRules.setCurrencyType(CurrencyType.Score);
			ITable table = new ClubMahjongTable(getRandomRoomId(), gameRules, roomer, clubId);
			addPrivateTable(table);
			return table;
		}
	}
	
	/**
	 * 创建麻将规则
	 * @param config
	 * @return
	 */
	public MahjongRules createMahjongGameRules(MahjongBaseRoomConfig config) {
		MahjongRules mahjongRules;
		if (config.getMType().equals(MahjongGameType.GANZHOU)) {
			// 赣州冲关
			mahjongRules = new GanZhouMahjongRules(config);
		} else {
			// 爆胡
			mahjongRules = new BaoHuRules(config);
		}
		return mahjongRules;
	}

	/**
	 * 模糊查找房间
	 * 
	 * @param idOrNO
	 * @return AbstractThreePokerTable
	 */
	public ITable findByID(int id) {
		if(privateTables.get(id) != null) {
			return privateTables.get(id);
		}
		return matchTables.get(id);
	}
	
	public void addMatchTable(ITable table) {
		synchronized (matchTables) {
			matchTables.putIfAbsent(table.getID(), table);
		}
	}
	
	public void addPrivateTable(ITable table) {
		synchronized (privateTables) {
			privateTables.putIfAbsent(table.getID(), table);
		}
	}
	
	private static Random random = new Random();
	
	/**
	 * 得到一个六位数的房间编号
	 */
	public Integer getRandomRoomId() {
		Integer roomId = null;
		synchronized (privateTableIds) {
			while (true) {
				roomId = 100000 + random.nextInt(900000);
				if (privateTableIds.contains(roomId)) {
					continue;
				}
				privateTableIds.add(roomId);
				return roomId;
			}
		}
	}

	/**
	 * 模糊查找房间
	 * 
	 * @param idOrNO
	 * @return AbstractThreePokerTable
	 */
	@SuppressWarnings("unchecked")
	public <T extends ITable> T fuzzyQuery(int id, Class<T> clazz) {
		return (T) findByID(id);
	}
	
	/**
	 * 获得某个俱乐部的所有房间
	 * 
	 * @return ITable
	 */
	public Collection<ITable> getClubTables(int clubID) {
		Collection<ITable> result = new ArrayList<ITable>();
		for (ITable table : privateTables.values()) {
			if (table instanceof ClubMahjongTable) {
				if (((ClubMahjongTable) table).getClubID() == clubID) {
					result.add(table);
				}
			}
		}
		return result;
	}

	public void destoryRoom(int tableId) {
		ITable table = findByID(tableId);
		if (table != null) {
			if(privateTables.remove(tableId) == null)
				matchTables.remove(tableId);
			table.destory();
		}
	}

	public void removePrivateTableByNo(Integer tableId) {
		synchronized (privateTableIds) {
			if (privateTableIds.contains(tableId)) {
				privateTableIds.remove(tableId);
			}
		}
	}
	
	/**
	 * 获取一个可以进入的匹配场房间号
	 * @param gameType
	 * @param gameLevel
	 * @return
	 */
	public Integer getCanEnterMatchTable(MahjongGameType gameType, MatchGameLevel gameLevel) {
		for (ITable table : matchTables.values()) {
			if(table instanceof MatchMahjongTable) {
				MatchMahjongTable mtable = (MatchMahjongTable)table;
				if(mtable.getGameType() == gameType && mtable.getGameLevel() == gameLevel && !mtable.isFull()) {
					return mtable.getID();
				}
			}
		}
		return null;
	}

}
